package app.utils;

import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;

@Slf4j
public class VerificationCode {

	/**
	 * 用于随机生成验证码的数据源
	 * 
	 * 去掉容易混淆的'O', '0','I', '1', 'L',
	 */
	private static final char[] source = new char[] { 'A', 'B', 'C', 'D', 'E',
			'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U',
			'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9' };

	/**
	 * 用于生成随机数的随机数生成器
	 */
	private static final Random rdm = new Random();

	private String text = "";

	private byte[] bytes = null;

	private String contentType = "image/png";

	public VerificationCode() throws NoSuchAlgorithmException {
	}

	public byte[] getImageBytes() {
		return this.bytes;
	}

	public String getContentType() {
		return this.contentType;
	}

	public void setContentType(String value) {
		this.contentType = value;
	}

	public int getContentLength() {
		return bytes.length;
	}

	private Random rand = SecureRandom.getInstanceStrong();

	/**
	 * 生成长度为4的随机字符串
	 */
	private void generateText(HttpSession session) {
		char[] verifySource = new char[4];
		for (int i = 0; i < verifySource.length; i++) {
			verifySource[i] = VerificationCode.source[rdm.nextInt(VerificationCode.source.length)];
		}
		text = new String(verifySource).toUpperCase();
		// 设置Session
		session.setAttribute("sessionSecurityName", text);
	}

	/**
	 * 在内存中生成打印了随机字符串的图片
	 * 
	 * @return 在内存中创建的打印了字符串的图片
	 */
	private BufferedImage createImage() {
		int width = 120;
		int height = 36;
		BufferedImage image = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		Graphics g = image.getGraphics();
		Graphics2D g2d = (Graphics2D) g;
		Random random = new Random();
		g.setColor(getRandomColor(200, 250));
		g.fillRect(0, 0, width, height);
		Font mFont = new Font("宋体", Font.BOLD, 28);
		g.setFont(mFont);
		g.setColor(getRandomColor(180, 200));
		// 画随机的线条
		for (int i = 0; i < 50; i++) {
			int x = random.nextInt(width - 1);
			int y = random.nextInt(height - 1);
			int x1 = random.nextInt(6) + 1;
			int y1 = random.nextInt(12) + 1;
			BasicStroke bs = new BasicStroke(2f, BasicStroke.CAP_BUTT,
					BasicStroke.JOIN_BEVEL);
			Line2D line = new Line2D.Double(x, y, x + x1, y + y1);
			g2d.setStroke(bs);
			g2d.draw(line);
		}
		// 输出随机的验证文字
		for (int i = 0; i < this.text.length(); i++) {

			String ctmp = this.text.substring(i, i + 1);
			Color color = new Color(20 + random.nextInt(110),
					20 + random.nextInt(110), 20 + random.nextInt(110));
			g.setColor(color);
			/** **随机缩放文字并将文字旋转指定角度* */
			// 将文字旋转指定角度
			Graphics2D g2d_word = (Graphics2D) g;
			AffineTransform trans = new AffineTransform();
			trans.rotate(random.nextInt(45) * 3.14 / 180, 22 * i + 8, 7);
			// 缩放文字
			float scaleSize = random.nextFloat() + 0.8f;
			if (scaleSize > 1f)
				scaleSize = 1f;
			trans.scale(scaleSize, scaleSize);
			g2d_word.setTransform(trans);
			/** ********************* */
			g.drawString(ctmp, 22 * i + 18, 22);

		}
		g.dispose();
		return image;
	}

	// 获取随机颜色
	private Color getRandomColor(int s, int e) {
		if (s > 255)
			s = 255;
		if (e > 255)
			e = 255;
		int r = s + this.rand.nextInt(e - s); // 随机生成RGB颜色中的r值
		int g = s + this.rand.nextInt(e - s); // 随机生成RGB颜色中的g值
		int b = s + this.rand.nextInt(e - s); // 随机生成RGB颜色中的b值
		return new Color(r, g, b);
	}

	/**
	 * 根据图片创建字节数组
	 * 
	 * @param image
	 *            用于创建字节数组的图片
	 */
	private void generatorImageBytes(BufferedImage image) {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try {
			javax.imageio.ImageIO.write(image, "jpg", bos);
			this.bytes = bos.toByteArray();
		} catch (Exception ex) {
			log.info(ex.getMessage());
		} finally {
			try {
				bos.close();
			} catch (Exception ex1) {
			}
		}
	}

	/**
	 * 被struts2过滤器调用的方法
	 * 
	 * @return 永远返回字符串"image"
	 */
	public InputStream doDefault(HttpSession session) {
		
		InputStream inputStream = null;
		
		this.generateText(session);
		BufferedImage image = this.createImage();

		ByteArrayOutputStream bos = new ByteArrayOutputStream();

		try {
			ImageIO.write(image, "jpg", bos);
			this.bytes = bos.toByteArray();
			
			inputStream = new ByteArrayInputStream(bytes);
			
		} catch (Exception ex) {
			log.error(ex.getMessage());
		} finally {
			try {
				bos.close();
			} catch (Exception ex1) {
				log.error(ex1.getMessage());
			}
		}
		return inputStream;
	}
}